package com.xcm.export.util;

import com.xcm.export.annotation.Cell;
import com.xcm.export.entity.Entity;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.springframework.core.io.ClassPathResource;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilderFactory;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.*;

/**
 * 导出Excel工具类
 */
public class SimpleExportUtil {

	private static SimpleExportUtil tool = new SimpleExportUtil();
	public static int PRECISION = 3;
	private static String DEFAULT_COLUMN_WIDTH = "3200";

	/**
	 * 创建标题行
	 *
	 * @param workbook HSSFWorkbook
	 * @param row      HSSFRow
	 * @param titles   List<Entity>
	 * @param sheet    HSSFSheet
	 */
	private void createTitileRow(HSSFWorkbook workbook, HSSFRow row, String[] titles, HSSFSheet sheet) {
		int length = titles.length;
		HSSFCellStyle style = workbook.createCellStyle();
		HSSFFont font = workbook.createFont();
		font.setColor((short) 12);
		font.setBoldweight((short) 14);
		style.setFont(font);
		style.setFillBackgroundColor((short) 13);
		for (int i = 0; i < length; ++i) {
			sheet.setColumnWidth(i, 2560);
			HSSFCell cell = row.createCell(i);
			cell.setCellValue(titles[i]);
			cell.setCellStyle(style);
		}
	}

	/**
	 * 创建标题行
	 *
	 * @param workbook   HSSFWorkbook
	 * @param row        HSSFRow
	 * @param entityList List<Entity>
	 * @param sheet      HSSFSheet
	 */
	private void createTitleRow(HSSFWorkbook workbook, HSSFRow row, List<Entity> entityList, HSSFSheet sheet) {
		HSSFCellStyle style = createHeadStyle(workbook);
//        HSSFFont font = workbook.createFont();
		//font.setColor((short)12);
		//font.setBoldweight((short)700);
		//style.setFont(font);
		//style.setFillBackgroundColor((short)13);
		int i = 0;
		for (Iterator localIterator = entityList.iterator(); localIterator.hasNext(); ) {
			Entity e = (Entity) localIterator.next();
			String columnWidth = e.getWidth();
			sheet.setColumnWidth(i, Integer.valueOf(columnWidth));
			HSSFCell cell = row.createCell(i);
			cell.setCellValue(e.getText());
			cell.setCellStyle(style);
			++i;
		}
	}

	/**
	 * 创建标题样式
	 *
	 * @param workbook HSSFWorkbook
	 * @return HSSFCellStyle
	 */
	private HSSFCellStyle createHeadStyle(HSSFWorkbook workbook) {
		HSSFCellStyle style = workbook.createCellStyle();
		style.setAlignment((short) 2);
		style.setVerticalAlignment((short) 1);
		style.setFillForegroundColor((short) 55);
		style.setFillPattern((short) 1);
		style.setBorderBottom((short) 1);
		style.setBorderLeft((short) 1);
		style.setBorderRight((short) 1);
		style.setBorderTop((short) 1);
		style.setWrapText(true);
		return style;
	}

	/**
	 * 创建单元格样式
	 *
	 * @param workbook HSSFWorkbook
	 * @return HSSFCellStyle
	 */
	private HSSFCellStyle createCellStyle(HSSFWorkbook workbook) {
		HSSFCellStyle style = workbook.createCellStyle();
		style.setAlignment((short) 2);
		style.setVerticalAlignment((short) 1);
		style.setFillForegroundColor((short) 9);
		HSSFFont font = workbook.createFont();
		font.setColor((short) 8);
		font.setFontHeightInPoints((short) 12);
		style.setWrapText(true);
		return style;
	}

	/**
	 * 解析xml文件
	 *
	 * @param clazz 封装导出到excel的POJO类
	 * @return List<Entity>
	 * @throws Exception
	 */
	private List<Entity> parseXML(Class<? extends Object> clazz) throws Exception {
		List list = new ArrayList();
		String clazzSimpleName = clazz.getSimpleName();
		//从classpath目录下加载xml文件，xml文件配置了具体要导出的列
		ClassPathResource classPathResource = new ClassPathResource("export/" + clazzSimpleName + ".ete.xml");
		InputStream inputStream = classPathResource.getInputStream();
		Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(inputStream);
		NodeList nodeList = doc.getElementsByTagName("property");
		for (int i = 0; i < nodeList.getLength(); ++i) {
			Element element = (Element) nodeList.item(i);
			Entity e = new Entity();
			e.setNeme(element.getAttribute("name"));
			e.setText(element.getAttribute("text"));
			e.setType(element.getAttribute("type"));
			String width = element.getAttribute("width");
			if (StringUtils.isBlank(width)) {
				//设置column默认宽度
				e.setWidth(DEFAULT_COLUMN_WIDTH);
			} else {
				e.setWidth(width);
			}
			list.add(e);
		}
		return list;
	}

	/**
	 * 解析注解
	 *
	 * @param clazz Class<? extends Object>
	 * @return List<Entity>
	 * @throws ClassNotFoundException
	 */
	private List<Entity> parseAnnotation(Class<? extends Object> clazz) throws ClassNotFoundException {
		List entities = new ArrayList();
		Field[] fields = clazz.getDeclaredFields();

		Field[] arrayOfField1 = fields;
		int j = fields.length;
		for (int i = 0; i < j; ++i) {
			Field field = arrayOfField1[i];
			Entity e = new Entity();
			boolean hasAnnotation = field.isAnnotationPresent(Cell.class);
			if (hasAnnotation) {
				Cell annotation = (Cell) field.getAnnotation(Cell.class);
				e.setText(annotation.title());
				e.setType(field.getType().getName());
				e.setNeme(field.getName());
				entities.add(e);
			}
		}
		return entities;
	}

	/**
	 * 导出数据到excel
	 *
	 * @param list      List<? extends Object>
	 * @param sheetName sheet名称
	 * @return HSSFWorkbook
	 * @throws Exception
	 */
	public static HSSFWorkbook exportToExcel(List<? extends Object> list, String sheetName) throws Exception {
		if (list == null || list.size() == 0) {
			//提示暂无内容
			HSSFWorkbook workbook = new HSSFWorkbook();
			HSSFSheet sheet = workbook.createSheet(sheetName);
			HSSFRow row = sheet.createRow(0);
			// 设置字体
			HSSFFont headfont = workbook.createFont();
			headfont.setFontName("黑体");
			// 字体大小
			headfont.setFontHeightInPoints((short) 22);
			// 加粗
			headfont.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
			HSSFCellStyle headstyle = workbook.createCellStyle();
			headstyle.setFont(headfont);
			// 左右居中
			headstyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
			// 上下居中
			headstyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
			// 创建第一行   
			HSSFRow row0 = sheet.createRow(0);
			// 设置行高
			row0.setHeight((short) 900);
			// 创建第一列
			HSSFCell cell0 = row0.createCell(0);
			cell0.setCellValue(new HSSFRichTextString("暂无数据！！！"));
			cell0.setCellStyle(headstyle);
			/**
			 * 合并单元格
			 *    第一个参数：第一个单元格的行数（从0开始）
			 *    第二个参数：第二个单元格的行数（从0开始）
			 *    第三个参数：第一个单元格的列数（从0开始）
			 *    第四个参数：第二个单元格的列数（从0开始）
			 */
			CellRangeAddress range = new CellRangeAddress(0, 0, 0, 7);
			sheet.addMergedRegion(range);
			return workbook;
		}
		BigDecimal bigDecimal = null;
		MathContext mathContext = new MathContext(PRECISION, RoundingMode.HALF_UP);
		Class clazz = list.get(0).getClass();
		//解析xml文件，解析出导出列
		List entities = tool.parseAnnotation(clazz);
		if ((entities == null) || (entities.size() == 0)) {
			entities = tool.parseXML(clazz);
		}
		//创建HSSFWorkbook
		HSSFWorkbook workbook = new HSSFWorkbook();
		//创建HSSFSheet
		HSSFSheet sheet = workbook.createSheet(sheetName);
		//创建HSSFRow
		HSSFRow titleRow = sheet.createRow(0);
		titleRow.setHeightInPoints(25.0F);
		//创建标题行
		tool.createTitleRow(workbook, titleRow, entities, sheet);

		int rowNum = 1;
		for (int i = 0; i < list.size(); ++i) {
			//创建行
			HSSFRow row = sheet.createRow(rowNum++);
			row.setHeightInPoints(23.0F);
			//HSSFCellStyle cellStyle = tool.createCellStyle(workbook);
			int colNum = 0;
			for (Iterator localIterator = entities.iterator(); localIterator.hasNext(); ) {
				Entity entity = (Entity) localIterator.next();
				String type = entity.getType();
				String name = entity.getNeme();
				//创建列
				HSSFCell cell = row.createCell(colNum);
				//cell.setCellStyle(cellStyle);
				Object obj = null;
				if (("boolean".equals(type)) || (type.equals("java.lang.Boolean"))) {
					obj = MethodToolUtil.executeMethod(list.get(i), MethodToolUtil.returnIsBooleanMethodName(name));
				} else {
					obj = MethodToolUtil.executeMethod(list.get(i), MethodToolUtil.returnGetMethodName(name));
				}
				//设置数据到列
				if (obj != null) {
					if (type.endsWith("String")) {
						cell.setCellValue((String) obj);
					} else if (("int".equals(type)) || (type.equals("java.lang.Integer"))) {
						cell.setCellValue(((Integer) obj).intValue());
					} else if (("double".equals(type)) || (type.equals("java.lang.Double"))) {
						bigDecimal = new BigDecimal(((Double) obj).doubleValue(), mathContext);
						cell.setCellValue(bigDecimal.doubleValue());
					} else if (("boolean".equals(type)) || (type.equals("java.lang.Boolean"))) {
						cell.setCellValue(((Boolean) MethodToolUtil.executeMethod(list.get(i), MethodToolUtil.returnIsBooleanMethodName(name))).booleanValue());
					} else if (("float".equals(type)) || (type.equals("java.lang.Float"))) {
						bigDecimal = new BigDecimal(((Float) obj).floatValue(), mathContext);
						cell.setCellValue(bigDecimal.doubleValue());
					} else if ((type.equals("java.util.Date")) || (type.endsWith("Date"))) {
						cell.setCellValue((Date) obj);
					} else if (type.equals("java.util.Calendar")) {
						cell.setCellValue((Calendar) obj);
					} else if (("char".equals(type)) || (type.equals("java.lang.Character"))) {
						cell.setCellValue(obj.toString());
					} else if (("long".equals(type)) || (type.equals("java.lang.Long"))) {
						cell.setCellValue(((Long) obj).longValue());
					} else if (("short".equals(type)) || (type.equals("java.lang.Short"))) {
						cell.setCellValue(((Short) obj).shortValue());
					} else if (type.equals("java.math.BigDecimal")) {
						bigDecimal = (BigDecimal) obj;
						bigDecimal = new BigDecimal(bigDecimal.doubleValue(), mathContext);
						cell.setCellValue(bigDecimal.doubleValue());
					} else {
						throw new Exception("data type errored!");
					}
				}
				++colNum;
			}
		}
		return workbook;
	}
}
